package org.bjf.modules.core.web.interceptor;

import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.bjf.exception.CommMsgCode;
import org.bjf.exception.ServiceException;
import org.bjf.modules.core.web.core.LoginInfo;
import org.bjf.modules.core.web.core.LoginRequired;
import org.bjf.modules.core.web.core.ThreadContext;
import org.bjf.modules.user.enums.RedisKey;
import org.bjf.utils.RedisUtil;
import org.bjf.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {

  @Autowired
  private RedisUtil redisUtil;

  @Override
  public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler) throws Exception {
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    LoginRequired loginRequired = handlerMethod.getMethodAnnotation(LoginRequired.class);
    if (loginRequired == null) {
      // 没有声明权限，直接放行
      return Boolean.TRUE;
    }

    String accessToken = getAccessToken(request);

    LoginInfo loginInfo = getLoginInfo(accessToken);

    // 登录用户信息放到ThreadLocal
    loginInfo.setLastTime(new Date());
    ThreadContext.setLoginInfo(loginInfo);

    return Boolean.TRUE;
  }

  private LoginInfo getLoginInfo(String accessToken) {
    // redis取登录用户信息
    String tokenKey = RedisKey.ACCESS_TOKEN.as(accessToken);
    LoginInfo loginInfo = redisUtil.get(tokenKey, LoginInfo.class);
    if (loginInfo == null) {
      throw new ServiceException(CommMsgCode.UNAUTHORIZED);
    }
    // 更新reids过期时间
    redisUtil.setex(tokenKey, loginInfo, 86400 * 15);

    return loginInfo;
  }

  private String getAccessToken(HttpServletRequest request) {
    String accessToken = request.getHeader("accessToken");
    if (StringUtils.isBlank(accessToken)) {
      accessToken = request.getParameter("accessToken");
      if (StringUtils.isBlank(accessToken) || !TokenUtil.verifyToken(accessToken)) {
        throw new ServiceException(CommMsgCode.UNAUTHORIZED);
      }
    }
    return accessToken;
  }
}
